//处理Promise https://developer.aliyun.com/article/613412
// https://juejin.cn/post/6994594642280857630
// 思路都是大同小异。
const resolvePromise = (promise2, x, resolve, reject) => {
  console.log(typeof x, promise2);
  if (promise2 === x) {
    reject(new Error("返回类型一样"));
    return;
  }

  if (x !== null && (typeof x === "object" || typeof x === "function")) {
    let called;
    try {
      // 防止x 返回的是promise
      let then = x.then;
      // 我们就认为他是promise,call他,因为then方法中的this来自自己的promise对象
      if (then === "function") {
        console.log("promise", then);
        then.call(
          x,
          (y) => {
            if (called) return;
            called = true;
            resolvePromise(promise2, y, resolve, reject);
          },
          (err) => {
            if (called) return;
            called = true;
            reject(err);
          }
        );
      } else {
        //如果是个普通对象就直接返回resolve作为结果
        resolve(x);
      }
    } catch (e) {
      if (called) return;
      called = true;
      reject(e);
    }
  } else {
    resolve(x);
  }
};

/** 用宏任务执行回调方法，或者存储当前回调，等resolve 处理 */
const handleData = (fn, value, promise2, resolve, reject) => {
  debugger;
  setTimeout(() => {
    try {
      const x = fn(value);
      resolvePromise(promise2, x, resolve, reject);
    } catch (error) {
      reject(error);
    }
  }, 0);
};

//  很多需求的时候，没有写过,就大致分析一下过程。写的过程优化
const PENDING = "PENDING";
const FULFILLED = "FULFILLED";
const REJECTED = "REJECTED";

class IPromise {
  constructor(executor) {
    this.state = PENDING;
    this.value = undefined;
    this.reason = undefined;
    // 存放
    this.onResolvedCallbacks = [];
    this.onRejectedCallbacks = [];

    try {
      executor?.(this.resolve, this.reject);
    } catch (error) {
      this.reject(error);
    }
  }
  /** resolve 改变状态，保存resolve 中存储的数据。
   *
   * （ static 静态方法父类不能直接调用，后public 是Ts，和java强类型的不太一样） */
  resolve = (value) => {
    // 转态发生变化，只接受第一改变。
    if (this.state === "PENDING") {
      this.value = value;
      this.state = FULFILLED;
      if (this.onResolvedCallbacks.length) {
        this.onResolvedCallbacks.forEach((fn) => fn());
      }
    }
  };

  reject = (reason) => {
    // 同样
    if (this.state === "PENDING") {
      this.reason = reason;
      this.state = REJECTED;
      if (this.onRejectedCallbacks.length) {
        this.onRejectedCallbacks.forEach((fn) => fn());
      }
    }
  };

  then(onFulfilled, onRejected) {
    if (!onFulfilled) onFulfilled = (x) => x;

    if (!onRejected) onRejected = (x) => x;

    let promise2 = new IPromise((resolve, reject) => {
      console.log("status" + this.state, "vlaue" + this.value);
      debugger;
      if (this.state === FULFILLED) {
        handleData(onFulfilled, this.value, promise2, resolve, reject);
      }

      if (this.state === REJECTED) {
        handleData(onRejected, this.reason, resolve, reject);
      }
      // 同步代码执行完毕后状态， 有异步的时候(存储当前状态)
      if (this.state === PENDING) {
        this.onResolvedCallbacks.push(() => {
          handleData(onFulfilled, this.value, promise2, resolve, reject);
        });
        this.onRejectedCallbacks.push(() => {
          handleData(onRejected, this.reason, resolve, reject);
        });
      }
    });
    return promise2;
  }
}

const promise = new IPromise((resolve, reject) => {
  setTimeout(() => {
    resolve("完成");
  }, 1000);
  // reject("失败");
  // resolve("完成");
})
  .then(
    (res) => {
      console.log(res);
      // 并不能直接调用(即使static)。
      debugger;
      return { name: "1123" };
    },
    (reason) => {
      console.log(reason);
    }
  )
  .then()
  .then((res) => {
    console.log("结果", res);
  });
